import Lxy_expression from './lxy_expression.js';
import Lxy_params_mgr from './lxy_params_mgr.js';

const ParamType_Exp = 0;
const ParamType_Object = 1;
const ParamType_Table = 3;
class Lxy_param_define {
	_type; // 0: 普通参数, 1: 对象，2: 对象数组, 3: 表格（二维数组）
	_param_name = '';
	_value_define = ''; // 值表达式定义;
}
class Lxy_obj_param_define extends Lxy_param_define {
	_params_define = [];
}
class Lxy_tab_param_define extends Lxy_param_define {
	_cols_define = []; // 表格中每列的定义;
	_data_start_index = 0; // 数据起始行;
}

class Lxy_page_event {
	_id = 0;
	_name = '';
	_input_params_define = []; // 输入参数定义;
	_output_params_define = []; // 输出参数定义;
	_dataSrc = null; // 定义数据源管理器， Lxy_params_mgr 对象

	constructor(paramsDefines) {
		if (!paramsDefines) {
			return;
		}

		if (paramsDefines.params) {
			this.initHandledParam(paramsDefines.params, null, 'Input');
		}
		if (paramsDefines.outParams) {
			this.initHandledParam(paramsDefines.outParams, null, 'Output');
		}
	}

	setDataSrcMgr(dataSrcMgr) {
		this._dataSrc = null;
		this._dataSrc = dataSrcMgr;
	}
	// pageData: 页面中作为计算输入参数的数据，并且eventConf中定义的输出参数也会放到pageData的下面;
	// inputData4Page: 跳转到当前页的输入参数
	// 页面定义的全局参数
	setDataSrc(pageData, inputData4Page, globalData) {
		this._dataSrc = null;
		this._dataSrc = new Lxy_params_mgr(pageData, inputData4Page, globalData);
	}

	// row: 如果是行操作，则为行的行号
	// expParams: 不同的事件所带的扩展参数
	// rowIndex：如果是行操作，则带的行号
	callEvent(expParams, rowIndex = -1) {}

	initHandledParam(paramsList, father, InOut) {
		if (!paramsList) {
			return;
		}

		if (!Array.isArray(paramsList)) {
			console.error('[Error]The params define list is not array, list: ', paramsList);
			return;
		}

		paramsList.forEach((params) => {
			const { name, type, value } = params;
			if (!name || type === undefined || value === undefined) {
				console.error('[Error]The params define(name, type value) is invalid, param define: ', params);
				return;
			}
			console.log('[Debug]param name: ', name, ', type: ', type, ', value: ', value);
			switch (type) {
				// 表达式
				case ParamType_Exp: {
					const suffixExp = Lxy_expression.toSuffixExp(value);
					this[`add${InOut}ParamsDefine`](ParamType_Exp, name, suffixExp, father);
					break;
				}
				// 对象
				case ParamType_Object: {
					const tmp = this[`add${InOut}ParamsDefine`](ParamType_Object, name, '', father);
					this.initHandledParam(params.values, tmp, InOut);
					break;
				}
				// 表格
				case ParamType_Table: {
					const fa = this[`add${InOut}ParamsDefine`](ParamType_Table, name, params.value, father);
					this.initHandledParam(params.values, fa, InOut);
					break;
				}
				default:
					break;
			}
		});
	}

	// value_exp: 参数值表达式;
	// 返回：返回新增加的参数定义对象;
	addInputParamsDefine(type, param_name, value_exp, parent) {
		// console.log('[Debug]add input param define, name: ', param_name, ', type: ', type, ', vaule: ', value_exp)
		let param_define = null;
		if (parent === null) {
			param_define = this.newParamsDefine(type, param_name, value_exp, this._input_params_define);
			this._input_params_define.push(param_define);
		} else {
			param_define = this.newParamsDefine(type, param_name, value_exp, parent);
			if (parent._type === ParamType_Table) {
				// 如果父节点是表格，则添加列定义;
				parent._cols_define.push(param_define);
			} else {
				parent._params_define.push(param_define);
			}
		}
		return param_define;
	}
	addOutputParamsDefine(type, param_name, value_exp, parent) {
		// console.log('[Debug]add out param define, name: ', param_name, ', type: ', type, ', vaule: ', value_exp)
		let param_define = null;
		if (parent === null) {
			param_define = this.newParamsDefine(type, param_name, value_exp, this._output_params_define);
			this._output_params_define.push(param_define);
		} else {
			param_define = this.newParamsDefine(type, param_name, value_exp, parent);
			if (parent._type === 3) {
				// 如果父节点是表格，则添加列定义;
				parent._cols_define.push(param_define);
			} else {
				parent._params_define.push(param_define);
			}
		}
		return param_define;
	}
	newParamsDefine(type, param_name, value_exp, parent) {
		let param_define = null;
		if (type === ParamType_Exp) {
			// eslint-disable-next-line new-cap
			param_define = new Lxy_param_define();
			param_define._type = 0;
			param_define._param_name = param_name;

			let varName = '';
			if (parent != null && parent._type === ParamType_Table) {
				// 父节点是表格的话，值表达式的变量要加上对应原数据中表格的路径(存放在parent的 _value_define 中);
				// eslint-disable-next-line space-in-parens
				for (let i = 0; i < value_exp.length; ) {
					if (i < value_exp.length - 2 && value_exp[i] === '$' && value_exp[i + 1] === '{') {
						let j = 0;
						for (j = i + 2; j < value_exp.length; j++) {
							if (value_exp[j] === '}') {
								break;
							} else {
								varName += value_exp[j];
							}
						}
						if (j === value_exp.length) {
							// 变量没有找到 } 符号
							return null;
						}

						param_define._value_define += '${';
						const end = varName.indexOf('[i]');
						if (end >= 0) {
							param_define._value_define += parent._value_define;
							param_define._value_define += '[i].';
							param_define._value_define += varName.substring(0, end);
						} else {
							param_define._value_define += varName;
						}
						param_define._value_define += '}';
						i = j + 1;
					} else {
						param_define._value_define += value_exp[i];
						i++;
					}
				}
			} else {
				param_define._value_define += value_exp;
			}
		} else if (type === ParamType_Object) {
			// eslint-disable-next-line new-cap
			param_define = new Lxy_obj_param_define();
			param_define._type = 1;
			param_define._param_name = param_name;
			param_define._value_define = value_exp;

			if (parent != null) {
				for (let i = 0; i < parent.length; i++) {
					if ((parent[i]._type === 1 || parent[i]._type === 2) && parent[i]._param_name === param_name) {
						parent[i]._type = 2;
						param_define._type = 2;
					}
				}
			}
		} else if (type === ParamType_Table) {
			param_define = new Lxy_tab_param_define();
			param_define._type = 3;
			param_define._param_name = param_name;
			param_define._value_define = value_exp;
		} else {
			return null;
		}

		return param_define;
	}
	// srcDatas : 计算表达式依赖的源数据, Lxy_params_mgr 对象
	// outputDataParent: 保存输出参数的父节点,输出参数将会保存在outputDataParent的下面
	calcOutParams(srcDatas, outputDataParent) {
		if (!this._output_params_define || this._output_params_define.length === 0 || !outputDataParent) {
			return true;
		}
		return this.calcParams(this._output_params_define, srcDatas, outputDataParent, -1);
	}
	// pageDatas : 计算表达式依赖的源数据, Lxy_params_mgr 对象
	calcInputParams(row_index = -1) {
		console.log('[Debug]calcInputParams, datas: ', this._dataSrc, this._input_params_define);
		if (this._input_params_define.length === 0) {
			return null;
		}
		const resultData = {};
		const ret = this.calcParams(this._input_params_define, this._dataSrc, resultData, row_index);
		if (ret === false) {
			return null;
		}
		return resultData;
	}
	calcInputParams2(resultData, row_index = -1) {
		console.log('[Debug]calcInputParams, datas: ', this._dataSrc);
		if (this._input_params_define.length === 0) {
			return true;
		}

		return this.calcParams(this._input_params_define, this._dataSrc, resultData, row_index);
	}
	// params_define: 参数表达式定义
	// srcDatas : 计算表达式依赖的源数据, Lxy_params_mgr 对象
	// parentData： 输出的父节点，计算结果放在parentData的下面;
	calcParams(params_define, srcDatas, parentData, row_index) {
		console.log('[Debug]calcParams, params_define: ', params_define, srcDatas);
		let value;
		let tmp;
		let tmpDefine;
		const cleans = [];
		let i = 0;
		for (i = 0; i < params_define.length; i++) {
			console.log('[Debug]calcParams, i: ', i, ', define: ', params_define[i]);
			if (params_define[i]._type === 0) {
				// 普通参数
				if (row_index < 0) {
					value = Lxy_expression.calcSuffixExp(params_define[i]._value_define, srcDatas);
				} else {
					const exp = this.pretreatExpression(params_define[i]._value_define, row_index);
					value = Lxy_expression.calcSuffixExp(exp, srcDatas);
				}
				if (value === null || value === Number.NaN) {
					console.error('[Error][event]Call expr fail, expr: ', params_define[i]._value_define);
					continue;
				}

				parentData[params_define[i]._param_name] = value;
			} else if (params_define[i]._type === 1) {
				// 对象;
				tmpDefine = params_define[i]._params_define;
				tmp = {};
				parentData[params_define[i]._param_name] = tmp;
				if (!this.calcParams(tmpDefine, srcDatas, tmp)) {
					console.error('[Error]calcParams obj fail, param define: ', tmpDefine);
					continue;
				}
			} else if (params_define[i]._type === 2) {
				// 对象数组;
				tmpDefine = params_define[i]._params_define;
				if (!cleans.hasOwnProperty(params_define[i]._param_name)) {
					// 清空原有数据;
					cleans[params_define[i]._param_name] = 'clean';
					if (parentData.hasOwnProperty(params_define[i]._param_name)) {
						parentData[params_define[i]._param_name].splice(0, parentData[params_define[i]._param_name].length);
					} else {
						parentData[params_define[i]._param_name] = [];
					}
				}
				tmp = {};
				parentData[params_define[i]._param_name].push(tmp);
				if (!this.calcParams(tmpDefine, srcDatas, tmp)) {
					console.error('[Error]calcParams array fail, param define: ', tmpDefine);
					continue;
				}
			} else if (params_define[i]._type === 3) {
				// 表格;
				value = srcDatas && srcDatas.getParam(params_define[i]._value_define); // value 应该是一个表格对象(二维数组);
				if (value === null || value === Number.NaN) {
					console.error('[Error]get table data fail, param define: ', params_define[i]._value_define);
					continue;
				}
				if (!Array.isArray(value)) {
					console.log('[Error]The table data is not array, data: ', value, ', param define: ', params_define[i]._value_define);
					continue;
				}
				// console.log('value=====',value)
				if (params_define[i]._cols_define.length === 0) {
					// 没有详细定义每列的表达式，则为整体表格赋值;
					// console.log('enter len =0')
					parentData[params_define[i]._param_name] = value;
					continue;
				}
				parentData[params_define[i]._param_name] = [];
				let exp;
				let param_name;
				for (let m = params_define[i]._data_start_index; m < value.length; m++) {
					const row = {};
					for (let n = 0; n < params_define[i]._cols_define.length; n++) {
						// 每行的值需要根据每列的定义来计算;
						exp = this.pretreatExpression(params_define[i]._cols_define[n]._value_define, m);
						tmp = Lxy_expression.calcSuffixExp(exp, srcDatas);
						if (tmp === null || tmp === Number.NaN) {
							console.error('[Error]calcSuffixExp fail, exp: ', exp);
							continue;
						}
						param_name = params_define[i]._cols_define[n]._param_name;
						row[param_name] = tmp;
						console.log('Tab i: ', i, ', n: ', n, ', name: ', param_name, ', value:', tmp);
					}
					parentData[params_define[i]._param_name].push(row);
				}
			} else {
				console.error('[Error][calcParams]Param define type is invalid, type:', params_define[i]._type);
				return false;
			}
		}
		return true;
	}
	pretreatExpression(exp, row_index) {
		const index = '[' + row_index + ']';
		return exp.replace(/\[i\]/g, index);
	}
}
export default Lxy_page_event;
